package com.atguigu.gulimall.cart.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.utils.R;
import com.atguigu.gulimall.cart.config.MyThreadConfig;
import com.atguigu.gulimall.cart.contrant.CartContract;
import com.atguigu.gulimall.cart.feign.ProductFeignService;
import com.atguigu.gulimall.cart.interceptor.CartInterceptor;
import com.atguigu.gulimall.cart.service.CartService;
import com.atguigu.gulimall.cart.to.SkuInfoTo;
import com.atguigu.gulimall.cart.to.UserInfoTo;
import com.atguigu.gulimall.cart.vo.CartItemVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ProductFeignService productFeignService;
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;


    @Override
    public CartItemVo addToCart(Long skuId, Integer num) {
        BoundHashOperations<String, Object, Object> boundHashOps = getHashOps();
        String cartItem = (String) boundHashOps.get(skuId);
        if (!StringUtils.isEmpty(cartItem)) {
            CartItemVo cartItemVo = JSON.parseObject(cartItem, CartItemVo.class);
            cartItemVo.setCount(cartItemVo.getCount() + num);
            boundHashOps.put(skuId, cartItemVo);
            return cartItemVo;
        } else {
            CartItemVo cartItemVo = new CartItemVo();
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                R info = productFeignService.info(skuId);
                SkuInfoTo skuInfo = info.getData("skuInfo", new TypeReference<SkuInfoTo>() {
                });
                cartItemVo.setSkuId(skuInfo.getSkuId());
                cartItemVo.setCheck(true);
                cartItemVo.setCount(1);
                cartItemVo.setImage(skuInfo.getSkuDefaultImg());
                cartItemVo.setPrice(cartItemVo.getPrice());
                cartItemVo.setTitle(skuInfo.getSkuTitle());
                cartItemVo.setTotalPrice(skuInfo.getPrice());
            }, threadPoolExecutor);

            CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
                List<String> setSkuAttrValues = productFeignService.getSkuSaleAttrValueBySkuId(skuId);
                cartItemVo.setSkuAttrValues(setSkuAttrValues);
            }, threadPoolExecutor);

            try {
                CompletableFuture.allOf(future, future1).get();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return cartItemVo;
        }
    }

    @Override
    public CartItemVo getCartItem(Long skuId) {
        BoundHashOperations<String, Object, Object> hashOps = getHashOps();
        String cartItemJson = (String) hashOps.get(skuId);
        return JSON.parseObject(cartItemJson, CartItemVo.class);
    }

    private List<CartItemVo> getCartItems(String cartKey) {
        BoundHashOperations<String, Object, Object> hashOps = getHashOps();
        List<Object> values = hashOps.values();
        if (values != null && values.size() > 0) {
            List<CartItemVo> collect = values.stream().map(object ->
                    JSON.parseObject((String) object, CartItemVo.class)
            ).collect(Collectors.toList());
            return collect;
        }
        return null;
    }

    @Override
    public List<CartItemVo> getUserCartItems() {
        UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
        String cartKey = CartContract.CART_PREFIX + userInfoTo.getUserId();
        List<CartItemVo> cartItems = getCartItems(cartKey);
        List<CartItemVo> collect = cartItems.stream().filter(cartItemVo -> cartItemVo.getCheck()).collect(Collectors.toList());
        return collect;
    }

    private BoundHashOperations<String, Object, Object> getHashOps() {
        UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
        String cartKey = "";
        if (userInfoTo.getUserId() != null) {
            cartKey = CartContract.CART_PREFIX + userInfoTo.getUserId();
        } else {
            cartKey = CartContract.CART_PREFIX + userInfoTo.getUserKey();
        }
        return redisTemplate.boundHashOps(cartKey);
    }
}
